const db = require('../libs/db')
const User = db.model('user')
const Log = db.model('log')
const Validator = require('vdjs')


exports.register = async ctx => {
  var oper = await ctx.user()
  var oid = oper && oper.id
  var valid = Validator.validate(ctx.request.body, {
    name: [
      {required: true, not: '', msg: '用户名不能为空'},
      {length: [2, 20], msg: '名字保持在2~20字符'}
    ],
    nickName: [
      {required: true, not: '', msg: '昵称不能为空'},
      {length: [2, 20], msg: '名字保持在2~20字符'}
    ],
    pass: [
      {required: true, not: '', msg: '密码不能为空'},
      {length: [6, 20], msg: '密码长度请保持6~20字符'}
    ],
    passConfirm: {required: true, eq: ctx.request.body.pass, msg: '两次输入密码不一致'}
  })
  if (valid.fails()) {
    await Log.create({
      uid: oid,
      ip: ctx.ip,
      action: 'register',
      result: 'false',
      desctiption: '创建用户，表单验证失败'
    })
    ctx.body = {
      bool: false,
      msg: valid.first(),
      valid: valid.all()
    }
    return false
  }
  var {name, email, pass, nickName} = ctx.request.body
  try {
    var result = await User.createUser({name, email, pass, nickName})
  } catch (err) {
    await Log.create({
      uid: oid,
      ip: ctx.ip,
      action: 'register',
      result: 'false',
      desctiption: '创建用户失败'
    })
    ctx.body = {
      bool: false,
      msg: '创建用户失败',
      err
    }
    return false
  }
  await Log.create({
    uid: oid,
    ip: ctx.ip,
    action: 'register',
    result: 'true',
    desctiption: '创建用户成功'
  })
  ctx.body = {
    bool: true,
    msg: '创建成功',
    result
  }
}

exports.login = async ctx => {
  await sleep(1500)
  var valid = Validator.validate(ctx.request.body, {
    name: {required: true, not: '', msg: '用户不能为空'},
    pass: {required: true, not: '', msg: '密码不能为空'}
  })
  if (valid.fails()) {
    await Log.create({
      ip: ctx.ip,
      action: 'login',
      result: 'false',
      desctiption: '用户登录，表单验证失败'
    })
    ctx.body = {
      bool: false,
      msg: valid.first(),
      valid: valid.all()
    }
    return false
  }
  var {name, pass} = ctx.request.body
  var check = await User.check(name, pass)
  if (check !== 1) {
    var msg = check === 0 ? '用户名与密码不匹配' : '用户不存在'
    await Log.create({
      ip: ctx.ip,
      action: 'login',
      result: check ? 'true' : 'false',
      desctiption: msg
    })
    ctx.body = {
      bool: false,
      check,
      msg
    }
    return false
  }
  var user = await User.findOne({where: {name}, attributes: {exclude: ['salt', 'pass']}})
  
  if (user.status === 0) {
    await Log.create({
      uid: user.id,
      ip: ctx.ip,
      action: 'login',
      result: 'false',
      desctiption: '用户已被禁用'
    })
    ctx.body = {
      bool: false,
      user: null,
      msg: '用户已被禁用'
    }
    return false
  }

  await Log.create({
    uid: user.id,
    ip: ctx.ip,
    action: 'login',
    result: 'true',
    desctiption: '用户登录'
  })
  var token = ctx.login(user)
  ctx.body = {
    bool: true,
    token,
    user,
    msg: '登录成功'
  }
}

exports.user = async ctx => {
  var {uid} = ctx.params
  if (!uid) {
    uid = ctx.state.auth.id
  } else {
    var oper = await ctx.user()
    if (oper.type !== 1000) {
      ctx.body = {
        bool: false,
        msg: '无权获取其他用户信息',
        result: null
      }
      return false
    }
  }
  user = await User.findOne({where: {id: uid}, attributes: {exclude: ['salt', 'pass']}})
  ctx.body = {
    bool: !!user,
    msg: user ? '' : '用户未找到',
    result: user
  }
}

exports.userList = async ctx => {
  var oper = await ctx.user()
  if (oper.type !== 1000) {
    ctx.body = {
      bool: false,
      msg: '无权获取其他用户信息',
      result: []
    }
    return false
  }
  var {ids} = ctx.query
  var where = {}
  if (ids) {
    ids = ids.split(',')
    where.id = {
      $in: ids
    }
  }
  var list = await User.findAll({where, attributes: {exclude: ['salt', 'pass']}})
  ctx.body = {
    bool: true,
    msg: '',
    result: list
  }
}

exports.delete = async ctx => {
  var uid = ctx.params.uid || ctx.query.uid
  if (!uid) {
    ctx.body = {
      bool: false,
      msg: '未提供用户uid参数'
    }
    return false
  }
  var oper = await ctx.user()
  log(oper)
  if (oper.id === ~~uid) {
    ctx.body = {
      bool: false,
      msg: '不能删除自己'
    }
    return false
  }
  if (oper.type !== 1000) {
    ctx.body = {
      bool: false,
      msg: '你没有权限操作'
    }
    return false
  }
  var result = await User.destroy({where: {id: uid}})
  var msg = result > 0 ? '删除成功' : '删除失败，没有这个用户'
  await Log.create({
    uid: oper.id,
    ip: ctx.ip,
    action: 'delete user',
    result: result ? 'true' : 'false',
    desctiption: `uid: ${uid}` + msg
  })
  ctx.body = {
    bool: result > 0,
    msg: msg,
    result
  }
}
// 修改基本信息
exports.update = async ctx => {
  var oper = await ctx.user()
  var uid = ctx.request.body.id
  // 非管理员只能修改自己信息
  if (oper.type !== 1000 && uid && ~~uid !== oper.id) {
    await Log.create({
      uid: oper.id,
      ip: ctx.ip,
      action: 'update user',
      result: 'false',
      desctiption: '权限不够，无法操作'
    })
    ctx.body = {
      bool: false,
      msg: '权限不够，无法操作'
    }
    return false
  }
  if (!uid) {
    uid = oper.id
  }
  var valid = Validator.validate(ctx.request.body, {
    id: {not: '', msg: 'id不能为空'},
    nickName: [
      {not: '', msg: '昵称不能为空'},
      {length: [2, 20], msg: '名字保持在2~20字符'}
    ],
    avator: {length: [0, 200], msg: 'avator不能超过200字符'},
    status: {not: '', msg: '状态不能为空'},
    type: {not: '', msg: '类型不能为空'}
  })
  if (valid.fails()) {
    await Log.create({
      uid: oper.id,
      ip: ctx.ip,
      action: 'update user',
      result: 'false',
      desctiption: '更新用户，表单验证失败'
    })
    ctx.body = {
      bool: false,
      msg: valid.first(),
      valid: valid.all()
    }
    return false
  }
  var {nickName, avator, status, type} = ctx.request.body
  // 自己不能修改状态，及类型
  if (oper.id === ~~uid) {
    data = {nickName, avator}
  } else {
    data = {nickName, avator, status, type}
  }
  for (var key in data) {
    if (typeof data[key] === 'undefined') {
      delete data[key]
    }
  }
  var result = await User.update(data, {where: {id: uid}})
  var bool = !!result[0]
  await Log.create({
    uid: oper.id,
    ip: ctx.ip,
    action: 'update user',
    result: bool ? 'success' : 'error',
    desctiption: `uid: ${uid}` + (bool ? '更新用户成功' : '更新用户失败，用户不存在')
  })
  ctx.body = {
    bool,
    msg: bool ? '更新成功' : '更新失败，用户不存在',
    result: result[0]
  }
}

// 更新密码
exports.reset = async ctx => {
  var oper = await ctx.user()
  var verify = {
    newPass: {required: true, length: [6, 20], not: '', msg: '新密码不能为空，并且6~20字符'},
    passConfirm: {required: true, eq: ctx.request.body.newPass, msg: '两次输入密码不一致'}
  }
  var {name, pass, newPass} = ctx.request.body
  // var {name, pass, newPass} =
  // 未登录，需要提供name,pass,newPass
  if (!oper) {
    verify.name = {required: true, not: '', msg: '用户名不能为空'}
    verify.pass = {required: true, not: '', msg: '请提供密码'}
  } else {
    if (name && name !== oper.name) {
      // 管理员修改其他，需要提供name,newPass
      if (oper.type !== 1000) {
        ctx.body = {
          bool: false,
          msg: '没有权限修改'
        }
        return false
      }
    } else {
      // 自己修改自己，需要提供pass,newPass
      verify.pass = {required: true, not: '', msg: '请提供密码'}
      name = oper.name
    }
  }
  var valid = Validator.validate(ctx.request.body, verify)
  if (valid.fails()) {
    ctx.body = {
      bool: false,
      msg: valid.first(),
      valid: valid.all()
    }
    return false
  }
  var certificate = {name, pass, newPass}
  var user = await User.findOne({where: {name}})
  if (!user) {
    await Log.create({
      uid: oper && oper.id,
      ip: ctx.ip,
      action: 'reset',
      result: 'false',
      desctiption: '重置密码成功失败，用户不存在'
    })
    ctx.body = {
      bool: false,
      msg: '不存在的用户'
    }
    return false
  }
  // 未登录修改，修改自己,需要验证旧密码
  if (pass) {
    var isPass = User.verify(pass, user.salt, user.pass)
    if (!isPass) {
      await Log.create({
        uid: oper && oper.id,
        ip: ctx.ip,
        action: 'reset',
        result: 'false',
        desctiption: '重置密码成功失败，旧密码不匹配'
      })
      ctx.body = {
        bool: false,
        msg: '旧密码不正确'
      }
      return false
    }
  }
  var newCertificate = User.createPass(newPass)
  user.pass = newCertificate.password
  user.salt = newCertificate.salt
  try {
    var result = await user.save()
  } catch (err) {
    await Log.create({
      uid: oper && oper.id,
      ip: ctx.ip,
      action: 'reset',
      result: 'false',
      desctiption: '重置密码成功失败，执行sql错误'
    })
    ctx.body = {
      bool: false,
      msg: '重置密码成功失败，执行sql错误',
      err
    }
    return false
  }
  await Log.create({
    uid: oper && oper.id,
    ip: ctx.ip,
    action: 'reset',
    result: 'true',
    desctiption: '重置密码成功'
  })
  ctx.body = {
    bool: true,
    msg: '重置密码成功',
    result: {
      id: user.id,
      name: user.name,
      nickName: user.nickName,
      type: user.type
    }
  }
}

// 修改账户名和昵称
exports.changeName = async ctx => {
  var valid = Validator.validate(ctx.request.body, {
    id: {required: true, not: '', msg: 'id不能为空'},
    pass: {required: true, not: '', msg: '密码不能为空'}
  })
  if (valid.fails()) {
    return ctx.body = {
      bool: false,
      msg: valid.first()
    }
  }
  var {id, name, nickName, pass} = ctx.request.body
  if (!name && !nickName) {
    return ctx.body = {
      bool: false,
      msg: '你必须提供要修改的账户名或者昵称'
    }
  }
  
  var user = await User.findOne({where: {id}})
  if (!user) {
    return ctx.body = {
      bool: false,
      msg: '用户不存在'
    }
  }
  if (!User.verify(pass, user.salt, user.pass)) {
    return ctx.body = {
      bool: false,
      msg: '密码与账号不匹配'
    }
  }
  var data = {}
  if (name) {
    data.name = name
  }
  if (nickName) {
    data.nickName = nickName
  }
  try {
    var result = await User.update(data, {where: {id}})
  } catch (err) {
    return ctx.body = {
      bool: false,
      msg: '更新失败',
      err
    }
  }
  return ctx.body = {
    bool: true,
    msg: '更新成功',
    result
  }
}
